package pl.flight2013.view;     

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateful;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.SessionScoped;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.jboss.solder.servlet.http.RequestParam;

import pl.flight2013.entity.Klient;

/**
 * Backing bean for Klient entities.
 * <p>
 * This class provides CRUD functionality for all Klient entities. It focuses
 * purely on Java EE 6 standards (e.g. <tt>&#64;ConversationScoped</tt> for
 * state management, <tt>PersistenceContext</tt> for persistence,
 * <tt>CriteriaBuilder</tt> for searches) rather than introducing a CRUD
 * framework or custom base class.
 */

@Named
@Stateful
@SessionScoped
public class KlientBean implements Serializable, KlientInterface {

	private static final long serialVersionUID = 1L;

	/*
	 * Support creating and retrieving Klient entities
	 */

	private Long id;

	public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	private Klient klient = new Klient();

	@Override
	public Klient getKlient() {
		return this.klient;
	}

	@Override
	public void setKlient(Klient klient) {
		this.klient = klient;
	}

	@RequestParam
	private String repeatUsername = new String();
	@RequestParam
	private String repeatPassword = new String();
	@Inject
	private Conversation conversation;

	@PersistenceContext(type = PersistenceContextType.EXTENDED)
	private EntityManager entityManager;

	public String create() {

		this.conversation.begin();
		return "create?faces-redirect=true";
	}

	@Override
	public String createNew() {
		// this.conversation.setTimeout(600000);
		System.out.println("------------- " + this.klient.getUsers().getUsername() + " " + repeatUsername + " " + repeatPassword + " ");
		System.out.println(this.klient.getUsers().getUsername().equals(getRepeatUsername()));

		if (this.klient.getUsers().getUsername().equals(this.repeatUsername) && this.klient.getUsers().getPassword().equals(this.repeatPassword) && this.klient.getUsers().getUsername() != null && this.klient.getUsers().getPassword() != null) {

			if (registerNewUser(this.klient)) {
				System.out.println("Założono użytkownika " + this.klient.getUsers().getUsername());
				this.klient = new Klient();
				return "/done";

			} 
		}

		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Błąd rejestracji."));
		return "/register";

	}

	private boolean registerNewUser(Klient klient) {
		try {
			entityManager.persist(klient);
			return true;
		} catch ( javax.persistence.PersistenceException e1){
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Taki użytkownik już istnieje."));
			return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

	public void retrieve() {

		if (FacesContext.getCurrentInstance().isPostback()) {
			return;
		}

		if (this.conversation.isTransient()) {
			this.conversation.begin();
		}

		if (this.id == null) {
			this.klient = this.example;
		} else {
			this.klient = findById(getId());
		}
	}

	public Klient findById(Long id) {

		return this.entityManager.find(Klient.class, id);
	}

	/*
	 * Support updating and deleting Klient entities
	 */

	public String update() {

		try {
			if (this.id == null) {
				this.entityManager.persist(this.klient);
				this.conversation.end();
				return "search?faces-redirect=true";
			} else {
				this.entityManager.merge(this.klient);
				this.conversation.end();
				return "view?faces-redirect=true&id=" + this.klient.getId();
			}
		} catch (Exception e) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
			return null;
		}
	}

	public String delete() {
		this.conversation.end();

		try {
			this.entityManager.remove(findById(getId()));
			this.entityManager.flush();
			return "search?faces-redirect=true";
		} catch (Exception e) {
			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage()));
			return null;
		}
	}

	/*
	 * Support searching Klient entities with pagination
	 */

	private int page;
	private long count;
	private List<Klient> pageItems;

	private Klient example = new Klient();

	public int getPage() {
		return this.page;
	}

	public void setPage(int page) {
		this.page = page;
	}

	public int getPageSize() {
		return 10;
	}

	public Klient getExample() {
		return this.example;
	}

	public void setExample(Klient example) {
		this.example = example;
	}

	public void search() {
		this.page = 0;
	}

	public void paginate() {

		CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();

		// Populate this.count

		CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
		Root<Klient> root = countCriteria.from(Klient.class);
		countCriteria = countCriteria.select(builder.count(root)).where(getSearchPredicates(root));
		this.count = this.entityManager.createQuery(countCriteria).getSingleResult();

		// Populate this.pageItems

		CriteriaQuery<Klient> criteria = builder.createQuery(Klient.class);
		root = criteria.from(Klient.class);
		TypedQuery<Klient> query = this.entityManager.createQuery(criteria.select(root).where(getSearchPredicates(root)));
		query.setFirstResult(this.page * getPageSize()).setMaxResults(getPageSize());
		this.pageItems = query.getResultList();
	}

	private Predicate[] getSearchPredicates(Root<Klient> root) {

		CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
		List<Predicate> predicatesList = new ArrayList<Predicate>();

		String imie = this.example.getImie();
		if (imie != null && !"".equals(imie)) {
			predicatesList.add(builder.like(root.<String> get("imie"), '%' + imie + '%'));
		}
		String nazwisko = this.example.getNazwisko();
		if (nazwisko != null && !"".equals(nazwisko)) {
			predicatesList.add(builder.like(root.<String> get("nazwisko"), '%' + nazwisko + '%'));
		}
		String miasto = this.example.getMiasto();
		if (miasto != null && !"".equals(miasto)) {
			predicatesList.add(builder.like(root.<String> get("miasto"), '%' + miasto + '%'));
		}
		String ulica = this.example.getUlica();
		if (ulica != null && !"".equals(ulica)) {
			predicatesList.add(builder.like(root.<String> get("ulica"), '%' + ulica + '%'));
		}
		String email = this.example.getEmail();
		if (email != null && !"".equals(email)) {
			predicatesList.add(builder.like(root.<String> get("email"), '%' + email + '%'));
		}

		return predicatesList.toArray(new Predicate[predicatesList.size()]);
	}

	public List<Klient> getPageItems() {
		return this.pageItems;
	}

	public long getCount() {
		return this.count;
	}

	/*
	 * Support listing and POSTing back Klient entities (e.g. from inside an
	 * HtmlSelectOneMenu)
	 */

	public List<Klient> getAll() {

		CriteriaQuery<Klient> criteria = this.entityManager.getCriteriaBuilder().createQuery(Klient.class);
		return this.entityManager.createQuery(criteria.select(criteria.from(Klient.class))).getResultList();
	}

	@Resource
	private SessionContext sessionContext;

	public Converter getConverter() {

		final KlientBean ejbProxy = this.sessionContext.getBusinessObject(KlientBean.class);

		return new Converter() {

			@Override
			public Object getAsObject(FacesContext context, UIComponent component, String value) {

				return ejbProxy.findById(Long.valueOf(value));
			}

			@Override
			public String getAsString(FacesContext context, UIComponent component, Object value) {

				if (value == null) {
					return "";
				}

				return String.valueOf(((Klient) value).getId());
			}
		};
	}

	/*
	 * Support adding children to bidirectional, one-to-many tables
	 */

	private Klient add = new Klient();

	public Klient getAdd() {
		return this.add;
	}

	public Klient getAdded() {
		Klient added = this.add;
		this.add = new Klient();
		return added;
	}

	@Override
	public String getRepeatUsername() {
		return repeatUsername;
	}

	@Override
	public void setRepeatUsername(String repeatUsername) {
		this.repeatUsername = repeatUsername;
	}

	@Override
	public String getRepeatPassword() {
		return repeatPassword;
	}

	@Override
	public void setRepeatPassword(String repeatPassword) {
		this.repeatPassword = repeatPassword;
	}
	
	
}